touch event phases being lost on button roll-overs and roll-offs?

Hello,

I’m not sure if this is a known issue (I’ve tried searching), or event an issue at all.

Basically, I’m trying to create a cursor-like object in my game that appears when the user touches the screen, moves with the user’s finger, and disappears when the user lifts the finger up. All is well and good until I introduce buttons.

I would like to have it so the cursor behaves regardless of whether the user has rolled over/off a button or other object. Now, I have a basic understanding of event propagation, so naturally all of my button listeners return false so that the touch events bubble up to the Runtime object where my cursor object is listening. Thus, my cursor and my buttons should be able to update.

The problem occurs when I touch down on the stage, roll over a button, then release. It also occurs when I touch down on a button, roll off the button, then release. Any time such change in context occurs, it appears the events don’t propagate to the Runtime object, even though I ‘think’ it should. It is as if the event is not fired at all.

Here is the basic code…

[lua]local function onButtonEvent (event)
– Button event function.
if “release” == event.phase then
– Do stuff…
end
– Return nothing so event is propagated.
end

– Button creation.
button = widget.newButton{
left = x,
top = y,
width = w,
height = h,
onEvent = onButtonEvent
}
– Also should note the button’s are invisible but hit-testable.
button.alpha = 0
button.isHitTestable = true
group:insert(button.view)[/lua]

[lua]local function onTouch (event)
if “began” == event.phase then
– Show cursor.
elseif “moved” == event.phase then
– Move cursor.
elseif “ended” == event.phase or “cancelled” == event.phase then
– Hide cursor.
end
end

Runtime:addEventListener(“touch”, onTouch)[/lua]

I should also note that I’ve tried adding button:addEventListener(“touch”, onButtonEvent) instead of passing an event handler in the button’s constructor, but that didn’t work. I’ve also read up on the whole display.getCurrentStage:setFocus(button) deal and so I tried that as well, which also didn’t work. I’ve also tried just passing the event manually to the cursor object but that didn’t work either, it is as if the event is not firing at all.

Has anyone else been able to solve this?

Many thanks,
Varen [import]uid: 86792 topic_id: 23479 reply_id: 323479[/import]

display.getCurrentStage:setFocus() is your answer. Perhaps you weren’t implementing it right?

It should look roughly like this:

local function onTouch(event)  
 if "began" == event.phase then  
 -- Show cursor.  
  
 -- Set focus so that all future touch events go to the button  
 -- (even if they are outside of the button)  
 display.getCurrentStage:setFocus(event.target)  
 elseif "moved" == event.phase then  
 -- Move cursor.  
 else  
 -- Hide cursor.  
  
 -- Release focus so that we can touch other things now  
 display.getCurrentStage:setFocus(nil)  
 end  
end  
  
button = widget.newButton{  
 left = x,  
 top = y,  
 width = w,  
 height = h,  
 onEvent = onButtonEvent  
}  
  
-- Also should note the button's are invisible but hit-testable.  
button.isVisible = false -- I'm pretty sure you want isVisible, not alpha  
button.isHitTestable = true  
button:addEventListener("touch", onTouch)  
group:insert(button.view)  

With multitouch it gets quite a bit trickier. See the docs for more:
http://developer.anscamobile.com/reference/index/stagesetfocus [import]uid: 87138 topic_id: 23479 reply_id: 94173[/import]

Hi Revaerie!

Thanks for the reply. Unfortunately, I still can’t get it working.

Despite using display.getCurrentStage():setFocus() method to maintain focus on the button, when I roll-off the button and release no event is fired anywhere. Conversly, the same thing happens when I roll-over the button and release, no event is fired.

Oddly enough, I’ve had the most success with the following formula:
[lua]local function onButtonEvent (event)
if “press” == event.phase then
– Do stuff
elseif “release” == event.phase then
– Do stuff
end
display.getCurrentStage():setFocus(nil)
end[/lua]

By releasing focus after any button event I manage to get the event to actually fire/propagate to the Runtime object. However, it only works when I initially click on the button then roll-off it and release - the cursor properly tracks the mouse and disappears. However, it doesn’t work when going the other way - starting off the button and doing a roll-over onto the button - the cursor does not track or disappear. i.e. only 50% of the problem is solved. So I tried changing the focus as well inside the Runtime touch listener but to no avail.

I’ve tried pretty much every permutation so I am about 60% sure at this point it has something to do with Corona. Time permitting, I will upload a full sample application to illustrate it.

Cheers,
Varen,
[import]uid: 86792 topic_id: 23479 reply_id: 94185[/import]

Varen, just double checking here - your event listener should be to the button itself not the runtime.

button:addEventListener("touch", onButtonEvent)  

Is this what you have? With widgets, you can just use the onEvent parameter so your don’t even need to explicitly use addEventListener with the code you already have.
Also, I just realized if all you really need to do with your widget button is track when it’s released, you’re probably better off doing the following, and it’ll give you the same behavior I think you’re looking for:

[code]
local function onButtonReleased(event)
– Run the code for when the button has been pressed
end

button = widget.newButton{
left = x,
top = y,
width = w,
height = h,
onRelease = onButtonReleased – onRelease will handle the button focus for you
}
[/code] [import]uid: 87138 topic_id: 23479 reply_id: 94188[/import]