The typical solution is to use only a touch listener and check the amount of time since the start of the touch when the touch finishes. An extension to this is to also recognise the touch as a touch and not a tap if it moves beyond a given distance, usually .03% of the screen width.
I typically start with this code:
local function touch(e) e.target = e.target or display.currentStage if (e.phase == "began") then e.target.hasFocus = true display.currentStage:setFocus( e.target ) e.target.begantime = e.time e.target.prev = e return true elseif (e.target.hasFocus) then local x, y = e.x-e.target.prev.x, e.y-e.target.prev.y e.target.x, e.target.y = e.target.x+x, e.target.y+y e.target.prev = e e.period = e.time - e.target.begantime if (e.phase == "moved") then else e.target.hasFocus = nil display.currentStage:setFocus( nil ) e.target.prev = nil e.target.begantime = nil end return true end return false end
But over time this has expanded into this function, which allows me to handle regular display object and physics body dragging. Just add the function with object:addEventListener(“touch”,touch):
local function touch(e) e.target = e.target or display.currentStage if (e.phase == "began") then e.target.hasFocus = true display.currentStage:setFocus( e.target ) e.target.begantime = e.time if (e.target.isBodyActive and e.target.bodyType ~= "static") then e.target.touchjoint = physics.newJoint( "touch", e.target, e.x, e.y ) e.target.touchjoint.dampingRatio = 1 e.target.touchjoint.frequency = 10 e.target.angularDamping = 1 else e.target.prev = e end if (e.target.began) then e.target:began(e) end return true elseif (e.target.hasFocus) then if (e.target.isBodyActive and e.target.bodyType ~= "static") then e.target.touchjoint:setTarget( e.x, e.y ) elseif (not e.target.doNotMove) then local x, y = e.x-e.target.prev.x, e.y-e.target.prev.y e.target.x, e.target.y = e.target.x+x, e.target.y+y e.target.prev = e end e.period = e.time - e.target.begantime if (e.phase == "moved") then if (e.target.moved) then e.target:moved(e) end else e.target.hasFocus = nil display.currentStage:setFocus( nil ) if (e.target.isBodyActive and e.target.bodyType ~= "static") then e.target.touchjoint:removeSelf() e.target.touchjoint = nil else e.target.prev = nil e.target.begantime = nil end if (e.target.ended) then e.target:ended(e) end end return true end return false end