Event.phase Never Goes To "moved", When An Item Is Inside A Newscrollvew

Hello there

I am trying to have my own objects inside a scrollview widget,

My objects need to have a touch event (my own custom buttons). 

The problem is that when I try to scroll the view, touching the objects it always runs the event of the object. 

I tried the solution that was suggested (using  event.phase == “moved” ) but it never gets to that event phase. The only event.phase it runs is “began”.

How do I handle this so that when the  “myOwnItem” is moved, it does not fire the touch event?

Bellow I have created a test code, simplified as much as possible in order to recreate and demonstrate the problem.

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true } local function myItemTouchListener( event ) print('the event phase is ' .. event.phase) if event.phase == "moved" then local dx = math.abs( event.x - event.xStart ) local dy = math.abs( event.y - event.yStart ) -- if finger drags button more than 5 pixels, pass focus to scrollView if dx \> 5 or dy \> 5 then scrollView:takeFocus( event ) end elseif event.phase=="began" then print ('we dont want this to run EVERY time!!') end end local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) scrollView:insert(myOwnItem) myOwnItem:addEventListener( "touch", myItemTouchListener )

Your button should probably not take any action unless it gets the “ended” phase.  If your acting on the Begin then that will not really work out for you as the button is on the top so gets a shot at the event first.

That is not what is happening. The button doesnt ever arrive at the ended phase.

Try the code bellow:

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true, } local function myItemTouchListener( event ) if event.phase=="ended" then print ('Success!!') end end local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) scrollView:insert(myOwnItem) myOwnItem:addEventListener( "touch", myItemTouchListener )

I am guessing that somehow I could/should tell the scroller to pass the event back to the button, if this is not a move, but there it gets complicated. The buttons are many and are created dynamically. Will keep on investigating. If you have an idea of how this would work, it would be welcome of course

Yea … i have coded around this before … not good solution.

Here is the issue … if you swallow the began phase then the scroll window never gets the began and will not scroll.  If you don’t swallow the began phase then the scroll window will never give you another chance at the event so button is not selected. 

If buttons are small then it seems to be ok to just assume that they will not try to scroll by touching a button first. and the following will work i think:

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true, } local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) local function myItemTouchListener( event ) print("event.phase: " .. event.phase) if (event.phase == "began") then display.getCurrentStage():setFocus( myOwnItem ) myOwnItem.isFocus = true return true elseif myOwnItem.isFocus then if event.phase == "moved" then -- --Release control as we are moving myOwnItem.isFocus = false display.getCurrentStage():setFocus( nil ) return false elseif event.phase == "ended" or event.phase == "cancelled" then -- reset touch focus display.getCurrentStage():setFocus( nil ) myOwnItem.isFocus = nil print ('Success!!') end end end scrollView:insert(myOwnItem) myOwnItem:addEventListener( "touch", myItemTouchListener )

however if you use “tap” for your button rather than touch it seems to work in a way that you want.

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true, } local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) local function myItemTouchListener( event ) print ('Success!!') end scrollView:insert(myOwnItem) myOwnItem:addEventListener( "tap", myItemTouchListener )

Good luck

Thank you, that did it!!

(on the simulator at least. It still needs to be tested on a device).

Just for the record, all this is in order to get around the problems that happened with the removal of the setFocus from the newScrollView that is mentioned at: 

http://forums.coronalabs.com/topic/33204-buttons-in-scrollview-not-registering-tap-correctly

Your button should probably not take any action unless it gets the “ended” phase.  If your acting on the Begin then that will not really work out for you as the button is on the top so gets a shot at the event first.

That is not what is happening. The button doesnt ever arrive at the ended phase.

Try the code bellow:

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true, } local function myItemTouchListener( event ) if event.phase=="ended" then print ('Success!!') end end local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) scrollView:insert(myOwnItem) myOwnItem:addEventListener( "touch", myItemTouchListener )

I am guessing that somehow I could/should tell the scroller to pass the event back to the button, if this is not a move, but there it gets complicated. The buttons are many and are created dynamically. Will keep on investigating. If you have an idea of how this would work, it would be welcome of course

Yea … i have coded around this before … not good solution.

Here is the issue … if you swallow the began phase then the scroll window never gets the began and will not scroll.  If you don’t swallow the began phase then the scroll window will never give you another chance at the event so button is not selected. 

If buttons are small then it seems to be ok to just assume that they will not try to scroll by touching a button first. and the following will work i think:

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true, } local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) local function myItemTouchListener( event ) print("event.phase: " .. event.phase) if (event.phase == "began") then display.getCurrentStage():setFocus( myOwnItem ) myOwnItem.isFocus = true return true elseif myOwnItem.isFocus then if event.phase == "moved" then -- --Release control as we are moving myOwnItem.isFocus = false display.getCurrentStage():setFocus( nil ) return false elseif event.phase == "ended" or event.phase == "cancelled" then -- reset touch focus display.getCurrentStage():setFocus( nil ) myOwnItem.isFocus = nil print ('Success!!') end end end scrollView:insert(myOwnItem) myOwnItem:addEventListener( "touch", myItemTouchListener )

however if you use “tap” for your button rather than touch it seems to work in a way that you want.

local widget = require( "widget" ) local scrollView = widget.newScrollView{ top = 5, left = 0, width = display.contentWidth, height = display.contentHeight , scrollWidth = display.contentWidth, scrollHeight = display.contentHeight, horizontalScrollDisabled = true, } local myOwnItem = display.newRect(2, 2, 300, 100) myOwnItem:setFillColor(255, 0, 0) local function myItemTouchListener( event ) print ('Success!!') end scrollView:insert(myOwnItem) myOwnItem:addEventListener( "tap", myItemTouchListener )

Good luck

Thank you, that did it!!

(on the simulator at least. It still needs to be tested on a device).

Just for the record, all this is in order to get around the problems that happened with the removal of the setFocus from the newScrollView that is mentioned at: 

http://forums.coronalabs.com/topic/33204-buttons-in-scrollview-not-registering-tap-correctly