I know I am resuming a trite and already discussed problem, but the solutions I found didn’t work in my case or I didn’t manage to apply them properly. So please help clarify this issue.
It’s about this object that serves as button:
If touch begins and ends on it everything is good.
If touch starts on it and finger is moved off of it end phase never gets triggered.
If touch is moved and lands on another touch object this latter only receives the end phase.
Here’s the code:
local function plusAll(event) if event.phase == "began" then beganTime = event.time plusAllButton.alpha = .5 elseif event.phase == "ended" then endedTime = event.time plusAllButton.alpha=1 if (endedTime - beganTime) \< 800 then -- does stuff else -- does other stuff end end return true end
I tried adding and removing focus respectively on begin and end phases but if touch is dragged off button focus gets never released (as no ended phase is dispatched)
I tried adding a moved phase and focus is released but still and end phase is being dispatched to an eventual other button that receives the final touch.
setting/removing focus should work. In your “begin” phase use display.currentStage:setFocus(button) (where button is your button object) and in your “ended” phase use display.currentStage:setFocus(nil).
The “ended” phase will fire even if the touch is moved off the button and released.
To detect if a touch is released on the button you could implement a function to check if the touch is currently on it.
local function eventWithinBounds(obj, event) local bounds = obj.contentBounds local x, y = event.x, event.y if ((x \>= bounds.xMin) and (x \<= bounds.xMax) and (y \>= bounds.yMin) and (y \<= bounds.yMax)) then return true end return false end local stage = display.getCurrentStage() local function onButtonTouch(event) local phase = event.phase local button = event.target if phase == "began" then stage:setFocus(button) button.isButtonPressed = true elseif phase == "moved" then if eventWithinBounds(button, event) then button.isButtonPressed = true else button.isButtonPressed = false end elseif phase == "ended" then stage:setFocus(nil) if button.isButtonPressed then button.isButtonPressed = false -- do something end end return true end
thanks for the answer. I’ve been experimenting with the following function so far without regards to the button boundaries, in the sense that I just release focus at the first move of the touch. The focus gets released from the object it started on but the touch still gets transfered to another button if I don’t lift the finger and move it onto this other object. Why do you think this is still happening?
local function plusAll(event) if event.phase == "began" then beganTime = event.time plusAllButton.alpha = 0.5 display.currentStage:setFocus(plusAllButton) elseif event.phase == "moved" then display.currentStage:setFocus(nil) plusAllButton.alpha = 1 return true elseif event.phase == "ended" then endedTime = event.time plusAllButton.alpha=1 display.currentStage:setFocus(nil) if (endedTime - beganTime) \< 800 then -- does stuff on other button if touch is transferred ???? else -- does stuff on other button if touch is transferred ???? end end return true end
thank you so much!!! Now I understand it better and implemented your code and it works great!!!
the only thing is I tested the ‘combo’ function system on only one button so I passed to eventWithinBounds only the event parameter and then used event.target instead of obj.
Obviously I’d need to use the same function for all my buttons, but how I do I pass the ‘obj’ paramater and ‘event’ when obj would correspond to a different button each time? I know I can’t do that from the eventListener I attach to every singlebutton or can I ?
basically I am stuck on:
buttonX:addEventListener(“touch”, onButtonTouch ) – ok to handle the touch effect
buttonX:addEventListener(“touch”, eventWithinBounds(obj, event)) — which I guess can’t be done…
thanks for the great help you’re helping me to learn a lot!!!
I guess the easiest is to add an ID to each button so that you can tell which button has been pressed in the event handler.
(The ID can be anything you want)
I’ve modified my event handler from above to take the ID into consideration:
local function eventWithinBounds(obj, event) local bounds = obj.contentBounds local x, y = event.x, event.y if ((x \>= bounds.xMin) and (x \<= bounds.xMax) and (y \>= bounds.yMin) and (y \<= bounds.yMax)) then return true end return false end local stage = display.getCurrentStage() local function onButtonTouch(event) local phase = event.phase local button = event.target if phase == "began" then stage:setFocus(button) button.isButtonPressed = true elseif phase == "moved" then if eventWithinBounds(button, event) then button.isButtonPressed = true else button.isButtonPressed = false end elseif phase == "ended" then stage:setFocus(nil) if button.isButtonPressed then button.isButtonPressed = false if button.id == "play" then -- play elseif button.id == "options" then -- show options elseif button.id == "rate" then -- show rate app end end end return true end
setting/removing focus should work. In your “begin” phase use display.currentStage:setFocus(button) (where button is your button object) and in your “ended” phase use display.currentStage:setFocus(nil).
The “ended” phase will fire even if the touch is moved off the button and released.
To detect if a touch is released on the button you could implement a function to check if the touch is currently on it.
local function eventWithinBounds(obj, event) local bounds = obj.contentBounds local x, y = event.x, event.y if ((x \>= bounds.xMin) and (x \<= bounds.xMax) and (y \>= bounds.yMin) and (y \<= bounds.yMax)) then return true end return false end local stage = display.getCurrentStage() local function onButtonTouch(event) local phase = event.phase local button = event.target if phase == "began" then stage:setFocus(button) button.isButtonPressed = true elseif phase == "moved" then if eventWithinBounds(button, event) then button.isButtonPressed = true else button.isButtonPressed = false end elseif phase == "ended" then stage:setFocus(nil) if button.isButtonPressed then button.isButtonPressed = false -- do something end end return true end
thanks for the answer. I’ve been experimenting with the following function so far without regards to the button boundaries, in the sense that I just release focus at the first move of the touch. The focus gets released from the object it started on but the touch still gets transfered to another button if I don’t lift the finger and move it onto this other object. Why do you think this is still happening?
local function plusAll(event) if event.phase == "began" then beganTime = event.time plusAllButton.alpha = 0.5 display.currentStage:setFocus(plusAllButton) elseif event.phase == "moved" then display.currentStage:setFocus(nil) plusAllButton.alpha = 1 return true elseif event.phase == "ended" then endedTime = event.time plusAllButton.alpha=1 display.currentStage:setFocus(nil) if (endedTime - beganTime) \< 800 then -- does stuff on other button if touch is transferred ???? else -- does stuff on other button if touch is transferred ???? end end return true end
thank you so much!!! Now I understand it better and implemented your code and it works great!!!
the only thing is I tested the ‘combo’ function system on only one button so I passed to eventWithinBounds only the event parameter and then used event.target instead of obj.
Obviously I’d need to use the same function for all my buttons, but how I do I pass the ‘obj’ paramater and ‘event’ when obj would correspond to a different button each time? I know I can’t do that from the eventListener I attach to every singlebutton or can I ?
basically I am stuck on:
buttonX:addEventListener(“touch”, onButtonTouch ) – ok to handle the touch effect
buttonX:addEventListener(“touch”, eventWithinBounds(obj, event)) — which I guess can’t be done…
thanks for the great help you’re helping me to learn a lot!!!
I guess the easiest is to add an ID to each button so that you can tell which button has been pressed in the event handler.
(The ID can be anything you want)
I’ve modified my event handler from above to take the ID into consideration:
local function eventWithinBounds(obj, event) local bounds = obj.contentBounds local x, y = event.x, event.y if ((x \>= bounds.xMin) and (x \<= bounds.xMax) and (y \>= bounds.yMin) and (y \<= bounds.yMax)) then return true end return false end local stage = display.getCurrentStage() local function onButtonTouch(event) local phase = event.phase local button = event.target if phase == "began" then stage:setFocus(button) button.isButtonPressed = true elseif phase == "moved" then if eventWithinBounds(button, event) then button.isButtonPressed = true else button.isButtonPressed = false end elseif phase == "ended" then stage:setFocus(nil) if button.isButtonPressed then button.isButtonPressed = false if button.id == "play" then -- play elseif button.id == "options" then -- show options elseif button.id == "rate" then -- show rate app end end end return true end