"began" and "ended" not firing on fast drag

Hi all,

I’m running into some issues where I have some images (imagine a line of 4 squares across the screen) with touch listeners enabled. I’m finding that if I try and move one quickly, sometimes the “began” and “ended” phases aren’t detected - just the “moved”. So the code that is supposed to reset the dragged square to its original position (when the touch has “ended”) isn’t running - leaving the images stranded where they were dropped.

Anyone seen anything like this before? Seems to happen only when I drag them very quickly.

I was thinking of possible solutions but they don’t seem very elegant. For example, if “moved” is detected, I could set a delayed check for a reasonable time that would put the moved object back if the “ended” code wasn’t run.

Hi @jeff15,

What’s most likely happening is that the “ended” phase is not triggering because it doesn’t actually end ON the object with listener. If you’re dealing with fast dragging of objects, you may want to use a method where the screen itself is detecting the touch and the object (which had to be “selected” for drag via a began phase) is the active object, and as the user drags around, that object snaps to the touch location, no matter where it is on the screen.

Hope this helps,

Brent

Hi Brent,

Thanks for your speedy reply (as usual!). Since it sometimes misses both the begin and ending phases, do you recommend somehow setting a flag or the like when a “began” is detected on the object itself so that a “moved” detection would only work if the flag was set? Seems weird that a “moved” phase would be detected without the “began” but that’s what I’m seeing occasionally. 

I’d be interested to see some code examples from anyone as well who has encountered this issue.

Cheers,

Jeff

I took a look at the demo “dragme” code and see that it checks for focus on the object, as below. I’ll try this approach:

[lua]

local function onTouch( event )

    local t = event.target

    – Print info about the event. For actual production code, you should

    – not call this function because it wastes CPU resources.

    printTouch(event)

    local phase = event.phase

    if “began” == phase then

        – Make target the top-most object

        local parent = t.parent

        parent:insert( t )

        display.getCurrentStage():setFocus( t )

        – Spurious events can be sent to the target, e.g. the user presses 

        – elsewhere on the screen and then moves the finger over the target.

        – To prevent this, we add this flag. Only when it’s true will “move”

        – events be sent to the target.

        t.isFocus = true

        – Store initial position

        t.x0 = event.x - t.x

        t.y0 = event.y - t.y

    elseif t.isFocus then

        if “moved” == phase then

            – Make object move (we subtract t.x0,t.y0 so that moves are

            – relative to initial grab point, rather than object “snapping”).

            t.x = event.x - t.x0

            t.y = event.y - t.y0

        elseif “ended” == phase or “cancelled” == phase then

            display.getCurrentStage():setFocus( nil )

            t.isFocus = false

        end

    end

    – Important to return true. This tells the system that the event

    – should not be propagated to listeners of any objects underneath.

    return true

end

[/lua]

Hi @jeff15,

What’s most likely happening is that the “ended” phase is not triggering because it doesn’t actually end ON the object with listener. If you’re dealing with fast dragging of objects, you may want to use a method where the screen itself is detecting the touch and the object (which had to be “selected” for drag via a began phase) is the active object, and as the user drags around, that object snaps to the touch location, no matter where it is on the screen.

Hope this helps,

Brent

Hi Brent,

Thanks for your speedy reply (as usual!). Since it sometimes misses both the begin and ending phases, do you recommend somehow setting a flag or the like when a “began” is detected on the object itself so that a “moved” detection would only work if the flag was set? Seems weird that a “moved” phase would be detected without the “began” but that’s what I’m seeing occasionally. 

I’d be interested to see some code examples from anyone as well who has encountered this issue.

Cheers,

Jeff

I took a look at the demo “dragme” code and see that it checks for focus on the object, as below. I’ll try this approach:

[lua]

local function onTouch( event )

    local t = event.target

    – Print info about the event. For actual production code, you should

    – not call this function because it wastes CPU resources.

    printTouch(event)

    local phase = event.phase

    if “began” == phase then

        – Make target the top-most object

        local parent = t.parent

        parent:insert( t )

        display.getCurrentStage():setFocus( t )

        – Spurious events can be sent to the target, e.g. the user presses 

        – elsewhere on the screen and then moves the finger over the target.

        – To prevent this, we add this flag. Only when it’s true will “move”

        – events be sent to the target.

        t.isFocus = true

        – Store initial position

        t.x0 = event.x - t.x

        t.y0 = event.y - t.y

    elseif t.isFocus then

        if “moved” == phase then

            – Make object move (we subtract t.x0,t.y0 so that moves are

            – relative to initial grab point, rather than object “snapping”).

            t.x = event.x - t.x0

            t.y = event.y - t.y0

        elseif “ended” == phase or “cancelled” == phase then

            display.getCurrentStage():setFocus( nil )

            t.isFocus = false

        end

    end

    – Important to return true. This tells the system that the event

    – should not be propagated to listeners of any objects underneath.

    return true

end

[/lua]