Rects on scrollViews reporting only phase "began"

There is a difference between Rects and Widget display objects on scrollViews regarding touch phases.

Posting in case this is not as intended and for discussion.

Code to reproduce:

rlistener=function(e)print(e.phase) --return true end function scene:create(e) sv=widget.newScrollView ( { top = 0, left = 0, width = 320, height = 568, scrollWidth = 320, horizontalScrollDisabled=true, } ) r=display.newRect(50,50,50,50) r:setFillColor(0) r:addEventListener("touch",rlistener) sv:insert(r) self.view:insert(sv) end

Expected result:

Listener logging the same touch phases as for other displayObjects.

Actual result:

Listener logs only the phase “began”.

 

To restore normal behavior,
a ) comment the line “sv:insert( r )”, or
b ) uncomment the line “return true”.

If you swap out the rect for a Widget object such as a Button or Label, b ) is not required. This is the difference in behavior.

This is not about how to use touch listeners, just a difference that I noted that I haven’t seen reflected in the documentation.

 

I believe you have to set the focus to the object in order to capture the ‘moved’ and ‘ended’ phases.

[lua]

if event.phase == “began” then

  display.getCurrentStage().setFocus(event.target)

end

if event.phase == “moved” then

  local dx = math.abs(event.y - event.yStart) + math.abs(event.x + event.xStart)

  if dx > 5 then  – moved finger more than 5 pixels

    display.getCurrentStage():setFocus(nil)

    event.target = sv._view

    event.phase = “began”

    sv._view.touch(sv._view, event)  – simulate a ‘began’ touch event on scrollView

  end

end

if event.phase == “ended” then

 display.getCurrentStage():setFocus(nil)

end

[/lua]

also, if you don’t return true then the event propogates, and as per nick_sherman, it may be (ie, not actually tested) the underlying scroll view itself then captures the event’s focus (so your rect would never see it again, because you effectively said “i’ll pass on it”)

I believe you have to set the focus to the object in order to capture the ‘moved’ and ‘ended’ phases.

[lua]

if event.phase == “began” then

  display.getCurrentStage().setFocus(event.target)

end

if event.phase == “moved” then

  local dx = math.abs(event.y - event.yStart) + math.abs(event.x + event.xStart)

  if dx > 5 then  – moved finger more than 5 pixels

    display.getCurrentStage():setFocus(nil)

    event.target = sv._view

    event.phase = “began”

    sv._view.touch(sv._view, event)  – simulate a ‘began’ touch event on scrollView

  end

end

if event.phase == “ended” then

 display.getCurrentStage():setFocus(nil)

end

[/lua]

also, if you don’t return true then the event propogates, and as per nick_sherman, it may be (ie, not actually tested) the underlying scroll view itself then captures the event’s focus (so your rect would never see it again, because you effectively said “i’ll pass on it”)