Chris Evans
Chris Evans

Reputation: 993

Corona: Double tap / single tap

I'm attempting to detect both single and double taps in Corona SDK. I have utilised:

system.setTapDelay(0.5)

...in my main.lua file which I understood would ensure a single tap event was not passed unless a further tap event had not been received in 0.5 seconds. According to the docs the delay is specified in seconds not milliseconds hence the 0.5.

I have then utilised this:

function mapGroup:tap(event)
    if event.numTaps >= 2 then
        print "double tap"
    else
        print "single tap"
    end
    return true
end

This, as expected returns single and double tap. However it is firing twice for double taps:

single tap
double tap

How can I prevent Corona firing the single tap until we know it is not going to be a double tap?

Upvotes: 2

Views: 2174

Answers (1)

David Roulin
David Roulin

Reputation: 86

It's more tricky than it seems at first.

I think system.setTapDelay() does work. At least it seems to. But my understanding is that is not meant to exclude single taps. Only to accept slower double taps. Or maybe the documentation of this function is just misleading. In any case let's hope the Corona dev team clarifies that in the future.

Now in your app you have objects that must react to single taps, and objects that must react to double taps, correct?

And maybe even objects that must react to one, or the other, but not to both. But you have to be aware that with this third design choice, in case of a single tap your object will have to "wait" until it is sure it wasn't the first hit of a double tap. You follow? In other words, to distinguish single and double taps on the same object might result in single taps that "lag" a bit.

To implement all of this in a simple way I would go like this:

function onSingleTap( event )
    if event.numTaps == 1 then
        print("received a single tap")
    end
end

objectThatRespondsToSingleTapOnly:addEventListener( "tap", onSingleTap )

function onDoubleTap( event )
    if event.numTaps >= 2 then
        print("received a double tap")
    end
end

objectThatRespondsToDoubleTapOnly:addEventListener( "tap", onDoubleTap )

Now if you also want objects that distinguish the single from the double you could add this:

local doubleTapTimeout = 600 -- values under 300 become hard to use
-- BTW make this a little higher than the tap delay, if you set it manually

function onExclusiveSingleTap( event )
    print("received an exclusive single tap")
end

function onExclusiveDoubleTap( event )
    print("received an exclusive double tap")
end

function onExclusiveTap( event )
    if event.numTaps == 1 then
        event.target.singleTapWaiting = timer.performWithDelay(
            doubleTapTimeout,
            function(e) onExclusiveSingleTap( event ) end
        )
    elseif event.numTaps >= 2 then
        timer.cancel( event.target.singleTapWaiting )
        onExclusiveDoubleTap( event )
    end
end

objectThatRespondsToBothTaps:addEventListener( "tap", onExclusiveTap )

I only wonder if you shouldn't copy the values of the event object in the Lua closure instead of passing its reference, which might result in some memory leaks.

function(e) onExclusiveSingleTap( {
    name = "tap",
    x = event.x,
    y = event.y,
    numTaps = 1,
    target = event.target
} ) end

Upvotes: 1

Related Questions