Distinguish between touch and tap

Hey guys!

I've been working on some ways to make a more unique way for my menuscreen and wanted to ask you if there is some good way to distinguish between touch and tap events?

Let's say I have a simple red square and would love to move it while touched, but to be rotated by 90° while tapped. NOTE: it should NOT be tapped while it is touched!

I thought about using a timer, but that sounds a bit like an overkill for something simple as that!
(I was also thinking about using event.numTaps (had that somewhere in my snippetJunk.. actually was surprised that I couldn't find that when searching for double Tap!)

Thanks in advance,
Chris

addEventListener("touch", touchFunc)
addEventListener('tap", tapFunc)

that doesn't work?

i mean, its not like we have docs....oh wait :-) /JK

http://developer.anscamobile.com/reference/index/objectaddeventlistener

http://developer.anscamobile.com/reference/index/events/tap

http://developer.anscamobile.com/reference/index/events/touch

.c

I'll jump in...

Okay, there are docs, but what happens if you have a touch *and* tap listener on an object?

When the user's finger hits that object, both of them will be fired, right? So there's no good way (that I can see off the top of my head) to determine whether the user is touching or tapping.

However, as a solution to the original problem, maybe forget about the "tap" even and go with touch. Then when the event.phase == ended you can check to see if event.x and event.y match event.xStart and event.yStart.

If they are the same then the user didn't move the object, they just touched and released -- so you could say that was a "tap" and rotate the object.

Jay

Hey Carlos!

Actually I've been trying this, but both will be fired when the red square is pressed (correct me if I'm wrong)!

1
2
3
4
5
6
7
8
9
10
11
12
local function rotationTest(event)
                if event.phase == "began" then
                        print("TOUCH")
                end
        end
        
        local function rotationTestSecond(event)
                print("TAP")
        end
        
        redSquare:addEventListener("touch",rotationTest)
        redSquare:addEventListener("tap",rotationTestSecond)

Hey J.A. Whye,

yes that's why I thought aswell but didn't like the attempt.
I also thought about using event.time, though it will return the time since the application launched, not since the function was fired!
I guess I'ld need to do some subtraction with system.getTimer (but everything I tried with it didn't work (tried to count the time of how long the user touches a button and had actually to use timer.performWithDelay.. grrr)

Now i tried this and it gives me errors when I try to print out the value of isTap.. And I have somehow no clue why:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
        local redSquare = display.newRect(display.contentWidth/2-50,display.contentHeight/2-50,100,100)
        redSquare:setFillColor(255,80,0)
        
        local isTap = true
 
local function rotationTest(event)
                --print("isTap start: "..isTap)
        if (event.phase == "began") then
                display.getCurrentStage():setFocus(redSquare)
                        redSquare.isFocus = true
            timer.performWithDelay(100,function() isTap=false end)
        elseif (redSquare.isFocus) then
                -- here we could also use your helpful inArea function J.A.Whye (found it after i did my own ._.)
                if (event.phase == "moved") then
                        --moved
                elseif (event.phase == "cancelled") or (event.phase == "ended") then
                        display.getCurrentStage():setFocus( redSquare, nil )
                                redSquare.isFocus = false
                if (isTap) then
                        -- square was released in under 100ms -> tap
                     print("TAB")
                else
                        -- if hold to long -> touch
                     print("TOUCH")
                end
            end
            -- resetting the bool
            --print("isTap end: "..isTap)
                        isTap = true
        end
end
redSquare:addEventListener("touch",rotationTest)

try this
Just tweaked your code a little bit... :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
local redSquare = display.newRect(display.contentWidth/2-50,display.contentHeight/2-50,100,100)
redSquare:setFillColor(255,80,0)
        
local isTap = true
local timer1
local function rotationTest(event)
        if (event.phase == "began") then
                        display.getCurrentStage():setFocus(redSquare)
                        redSquare.isFocus = true
                        timer1 = timer.performWithDelay(100,function() isTap=false end)
        elseif (redSquare.isFocus) then
                        if (event.phase == "moved") then
                                        --moved
                        elseif (event.phase == "cancelled") or (event.phase == "ended") then
                                        display.getCurrentStage():setFocus( redSquare, nil )
                                                        redSquare.isFocus = false
                                        if (isTap) then
                                                -- square was released in under 100ms -> tap
                                                 print("TAP")
                                        else
                                                -- if hold to long -> touch
                                                 print("TOUCH")
                                        end
                                        isTap = true
                                        timer.cancel(timer1)
                        end      
        end
end
redSquare:addEventListener("touch",rotationTest)

Here's a simple method that uses logic instead of timers or finger positions. Use it as a touch listener (don't even bother listening for taps).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
local isTap -- forward declare
local function touchSquare(event)
     if event.phase == "began" then 
          isTap = true --it's potentially a tap or a touch
          --don't do anything else yet.  
     elseif event.phase == "moved" then
          isTap = false -- finger moved, so NOT a tap
          --do touch dragging functionality here
 
     elseif event.phase == "ended" and isTap == true then --it IS a tap
          --do tap functionality here
 
     end
end

@XeonBL good work
I think its working as expected.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local redSquare = display.newRect(display.contentWidth/2-50,display.contentHeight/2-50,100,100)
redSquare:setFillColor(255,80,0)
                                
local isTap -- forward declare
local function touchSquare(event)
     if event.phase == "began" then 
          isTap = true --it's potentially a tap or a touch
          --don't do anything else yet.  
     elseif event.phase == "moved" then
          isTap = false -- finger moved, so NOT a tap
          redSquare.x = event.x
                  redSquare.y = event.y
 
      elseif event.phase == "ended"  and  isTap == true then
                   print("tap")
                   redSquare:rotate( 60 )
     end
end
redSquare:addEventListener("touch",touchSquare)

@renvis@technowand

Thanks! Didn't thought that the timer was the problem :D (maybe because it was already 2.a.m..)

@XenonBL

Thanks for your script, but it actually doesn't do what I requiered :/
Let's imagine I would have a square that should fill up with a color while it's touched, but rotate if it will be tapped.
With your solution, if the user won't move it's finger while touching, it will rotate after the touch is ended.

It works now with the timer as expected :)
I thought that my idea would work, but didn't know if there would be a better way :/

Thanks guys for your help!
If you still have some ideas, let me know!

@xxxfanta
True, my method requires finger movement to register as a touch. That's what I thought you meant when you said "would love to move it while touched" in your original post.

views:1986 update:2011/9/25 12:40:18
corona forums © 2003-2011