Script for detecting double tap, long tap, pinch, etc

The place to discuss anything and everything about running your LiveCode on Android

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
FabricioRocha
Posts: 25
Joined: Sun Jan 19, 2014 8:53 pm

Script for detecting double tap, long tap, pinch, etc

Post by FabricioRocha » Wed Mar 19, 2014 3:45 pm

Hi everyone!

I don't know if this is the right place for such things, but as there are so many newbies like me trying Livecode in Android here, I supposed that this might be useful for some :)

I created a script for translating the touchStart/touchEnd/touchMove messages into some common mobile gestures. It finally worked (somehow) in my initial tests and I would like to share it, hoping it will be useful and possibly improved. I would be glad to see some tips and suggestions from the more experienced Livecoders. GPL spirit!

It is meant to be a frontscript. Put it in a card, then in other card of your app use "insert script ... into front".

Thanks and best regards!

Fabricio Rocha
Brasilia, Brasil

Code: Select all

-- Touches 0.1 - 19 Mar 2014
-- Fabricio Rocha
/* A frontscript for translating the usual touch messages into "more mobile" gestures. The following messages are
generated and sent to their targets:

shortTap - Fast touch
doubleTap - Two successive taps on a same control
tripleTap - Three successive taps on a same control
longTap - A single, longer tap on a control
pinch percentvariation - A pinch gesture in a control, along with the + or - percentage variation of the fingers
    distance in comparison to their original positions.

VERSION NOTES:

0.1
Due to a difficulty in detecting the right start location of a touch, I could not precisely define the position of
successive taps, so the target control was used as the reference. This means that two far but successive taps on a 
big control will generate a doubleTap message, a behaviour which could not suit some applications.

*/

-- Fixed constants. Change them at your will, substitute them by preferences, etc
constant cMultiTapGap = 240, cShortTapDuration = 300, cTapDistIgnore = 5

local arrTouches, lastTapTime = 0, lastTapTgt="", tapCount=1, pendingMsg


on touchStart tID
    put the milliseconds into arrTouches[tID]["timeStart"]
    put the target into arrTouches[tID]["tgt"]
    
    if lastTapTime <> 0 then
        if (arrTouches[tID]["timeStart"] - lastTapTime) < cMultiTapGap then
            if arrTouches[tID]["tgt"] = lastTapTgt then
                -- Sequencial touches in the same target
                add 1 to tapCount
            end if
        else
            -- Touches were time-spaced
            put 1 into tapCount
        end if
    end if
end touchStart


on touchEnd tID
    put the milliseconds into lastTapTime
    put arrTouches[tID]["timeStart"] into stTime
    put arrTouches[tID]["posStart"] into stPos
    put arrTouches[tID]["tgt"] into tgt
    put arrTouches[tID]["posLast"] into lastTapPos
    delete variable arrTouches[tID]
    
    put tgt into lastTapTgt
   
    if (lastTapTime - stTime) < cShortTapDuration then
        cancel pendingmsg
        put "" into tapmsg
        switch TapCount
            case 1
                put "shortTap" into tapmsg
                break
            case 2
                put "doubleTap" into tapmsg
                break
            case 3
                put "tripleTap" into tapmsg
                break
        end switch
    else
        if distance (lastTapPos, stPos) < cTapDistIgnore then
            put "longTap" into tapmsg
        end if
    end if
    
    send tapmsg && tID to tgt in cMultiTapGap milliseconds
    put the result into pendingmsg
end touchEnd



on touchMove tID, tX, tY
    -- This event is triggered whenever the touch starts, even if position did not change.
    
    if arrTouches[tID]["posStart"] is empty then
        -- Touch had just started.
        put (tX,tY) into arrTouches[tID]["posStart"]
    end if
    
    -- Update the current touch location
    put tX & comma & tY into arrTouches[tID]["posLast"]

    -- Ignore movement if it is lower than our predefined minimal movement.
    if distance ((tX,tY), arrTouches[tID]["posStart"]) <= cTapDistIgnore then
        exit touchMove
    end if
    
    -- Simultaneous touches?
    put the number of lines of the keys of arrTouches into numTouches
    
    if numTouches = 1 then
        -- Single touch. Just pass the message.
        pass touchMove
        
    else if numTouches = 2 then
        -- If there are two touches happening, we might have a pinch gesture
        put line 1 of the keys of arrTouches into touch1id
        put line 2 of the keys of arrTouches into touch2id
        
        put distance (arrTouches[touch1id]["posStart"], arrTouches[touch2id]["posStart"]) into startDist
        put distance (arrTouches[touch1id]["posLast"], arrTouches[touch2id]["posLast"]) into curDist
        
        -- With some "if"s here, we might detect a double drag gesture or something else
        
        -- The parameter to the "pinch" message will be the variation of the distance in percentage.
        put (curDist - startDist)/startDist * 100 into deltaPerc
        
        send "pinch" && deltaPerc to arrTouches[touch1id]["tgt"]
        
    end if
    
end touchMove

-- distance
-- Returns the distance between points p1 and p2, each point being a list of x,y coordinates
function distance p1, p2
    put (item 1 of p1) - (item 1 of p2) into deltaX
    put (item 2 of p1) - (item 2 of p2) into deltaY
    
    put the sqrt of ((deltaX * deltaX) + (deltaY * deltaY)) into delta
    
    return the round of delta
end distance

Post Reply