Doubletap + Storyboard

7 replies [Last post]
Yogamatta's picture
Yogamatta
User offline. Last seen 2 days 1 hour ago. Offline
Joined: 22 Feb 2011

Hello folks,

I've got a small problem. Let me describe what I want to do. I am doing a picture book using storyboard API. I have a couple of arrows to navigate between pages. I don't want to have a home button. Therefore I came up with an idea - if a user singel taps an arrow, next page is shown. But double tap would show the first page.

The issue is that there is no event "doubletap" only "tap". There is of cause numTaps. But if a user double taps an object the tap even is called 2 times: first where numTaps = 1 and second with numTaps = 2.

I thought I could manage this as follows (please note this is not a complete code)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
local numTaps
local timerStash = {}
 
local function goToScene()
    if numTaps > 1 then
       timer.cancel(timerStash[1])
       storyboard.gotoScene(true, "firstPage", effect, 500)
    else
        storyboard.gotoScene(true, nextPage, effect, 500)
    end
end
 
local function turnPage(event)
    numTaps = event.numTaps
 
    table.insert(timerStash, timer.performWithDelay(350, goToScene, 1))
end

But this thing just crashes.

Please help. Thanks in advance.

Replies

robmiracle's picture
robmiracle
User offline. Last seen 8 hours 3 min ago. Offline
Joined: 18 Jan 2011

Try this:

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
33
34
35
    local previousTapTime = 0
    tapAbsorber = display.newRect(0,0,display.contentWidth,display.contentHeight)
 
    local function tapAbsorberHandler(event)
        print("event.phase", event.phase)
--
-- in my app this is sitting on top of a scroll view (sv) and I want
-- any movement gestures to go to the scroll view.
-- the "ended" phase has the double tap code in it.
--
        if event.phase == "moved" then
            if math.abs(event.xStart - event.x) > 5 or math.abs(event.yStart - event.y) then 
                sv:takeFocus(event)
                return true
            end
        elseif event.phase == "ended" then
            print("e.time - ptt", event.time - previousTapTime)
            if (event.time - previousTapTime) < 300 then -- double tap so close
                print("double tap")
                storyboard.gotoScene(previousScene)
                return true
            end
            previousTapTime = event.time
        end
        return true
    end
 
 
    tapAbsorber:setReferencePoint(display.TopLeftReferencePoint)
    tapAbsorber.x = 0
    tapAbsorber.y = 0
    tapAbsorber.alpha = 0
    tapAbsorber.isHitTestable = true
    tapAbsorber:addEventListener("touch", tapAbsorberHandler)
    group:insert(tapAbsorber)

You have to use a touch handler, not a tap handler since I don't think the event.time is passed on tap.

Yogamatta's picture
Yogamatta
User offline. Last seen 2 days 1 hour ago. Offline
Joined: 22 Feb 2011

Thank you. Unfortunately it's the same issue here. Your code is handeling only double tap. My problem is that I need to handle both single and double-tap. What happens is that both events are caught. So I need somehow to cancel an action of the first event if double-tap is detected. I just can'r figure out how to do that.

robmiracle's picture
robmiracle
User offline. Last seen 8 hours 3 min ago. Offline
Joined: 18 Jan 2011

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
33
    local function tapAbsorberHandler(event)
        print("event.phase", event.phase)
--
-- in my app this is sitting on top of a scroll view (sv) and I want
-- any movement gestures to go to the scroll view.
-- the "ended" phase has the double tap code in it.
--
        if event.phase == "moved" then
            if math.abs(event.xStart - event.x) > 5 or math.abs(event.yStart - event.y) then 
                sv:takeFocus(event)
                return true
            end
        elseif event.phase == "ended" then
            print("e.time - ptt", event.time - previousTapTime)
            if (event.time - previousTapTime) < 300 then -- double tap so close
--
-- do what you need to on a double tap for example
--
                print("double tap")
                storyboard.gotoScene(previousScene)
                return true
--
-- added this bit
--  
            else
--
-- do whatever you want to do on a single tap
--
            end
            previousTapTime = event.time
        end
        return true
    end

Yogamatta's picture
Yogamatta
User offline. Last seen 2 days 1 hour ago. Offline
Joined: 22 Feb 2011

Well. I want to switch scenes both when i tap and double-tap. So this suggestion doesn't work. The reason is that if a switch begins during first tap, the second one never registeres. But I finally solved it. Here's how

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
local nextScene
local timer1, timer2
local gfp = false
 
-- go to next scene cancel all timers 
local function goToNextScen()
        storyboard.gotoScene(true, nextScene, effect, 500)
 
        if timer1 then
                timer.cancel(timer1)
        end
        if timer2 then
                timer.cancel(timer2)
        end
        return true
end
 
-- turn page
local function turnPage(event)
 
        if event.phase == "ended" then
                -- if double-tap 
                if event.time - previousTapTime < 300 then
                        -- we can go to first page
                        gfp = true
                        -- fix what needed to be done to go to first page
                        nextScene = "firstPage"
                else 
                        -- do not go to first page
                        gfp = fale
                       -- fix what needed to be done to go to next page
                        nextScene = ...
                end
                
                -- now this event will be called twice for each tap. 
                -- so we start to actually change to new scene first after 300 ms
                -- if during that time double-tap happens, we cancel the first call
                -- now we can go to first page
                if gfp then
                        timer.cancel(timer1)
                        timer2 = timer.performWithDelay(300, goToNextScen, 1)
                else
                        timer1 = timer.performWithDelay(300, goToNextScen, 1)
                end 
                
                previousTapTime = event.time
        end 
        
        return true
end

platt.eric
User offline. Last seen 3 weeks 6 days ago. Offline
Joined: 18 Feb 2012

Yogamatta, does this incur a delay after the taps before there is a response (300 milliseconds)?

I'm trying to write a routine that detects doubletaps without a delay (that doesn't also trigger single tap response), if possible.

Thanks,
Eric

Yogamatta's picture
Yogamatta
User offline. Last seen 2 days 1 hour ago. Offline
Joined: 22 Feb 2011

Well, there is a delay of cause. But there was a major delay bug with storyboard and transitions. With Those 2 delays combining it was very noticible. But I haven't had a chance to test with the latest fix and see how it looks like only with 300ms delay.

I don't think there is a way to solve it without a delay. If you find one, please share the solution. Good luck.

platt.eric
User offline. Last seen 3 weeks 6 days ago. Offline
Joined: 18 Feb 2012

It's a dilemna (if you don't want a delay for a tap), because you have to wait to see if a double tap happens before you respond to the single tap!

Besides using tachyons that tunnel backward through time, I don't know what the solution would be. :)

But maybe I'm just not seeing it ...
I will keep you posted.

By the way, I used 200 milliseconds in my solution, and it seems fine. YMMV.

Thanks

Eric

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.